/** @format */

import { findPass } from '../utils/findPass'
import { formatDBQuery, formatUpdateOperator } from '../utils/formatWx'

export class WxBaseDao {
  private db: any
  constructor(context: any, private dbName: string) {
    this.db = context.cloud.db
    this.dbName = dbName
  }
  /**
   * 查询一条数据
   * @param query
   * @param projection
   */
  async findOne(query: Record<string, any>, projection: Record<string, any> = {}, force = false) {
    const formatedQuery = formatDBQuery(this.db, query)

    const conditions = Object.keys(projection)

    let sql = this.db.collection(this.dbName).where(formatedQuery).limit(1)

    conditions.forEach(key => {
      if (key === 'projection') {
        sql = sql.field(projection[key])
      }
      if (key === 'skip') {
        sql = sql.skip(projection[key])
      }
      if (key === 'sort') {
        Object.keys(projection.sort).forEach(sortKey => {
          sql = sql.orderBy(sortKey, projection.sort?.[sortKey] === 1 ? 'asc' : 'desc')
        })
      }
    })

    const result = await sql.get()
    return result?.data?.[0]
  }
  /**
   * 查询多条数据
   * @param query
   * @param projection
   */
  async find(query: Record<string, any>, projection: Record<string, any> = {}, force = false) {
    const formatedQuery = formatDBQuery(this.db, query)
    const conditions = Object.keys(projection)

    let sql = this.db.collection(this.dbName).where(formatedQuery)

    if (!Object.keys(query).length) {
      sql = this.db.collection(this.dbName)
    }
    conditions.forEach(key => {
      if (key === 'projection') {
        sql = sql.field(projection[key])
      }
      if (key === 'limit') {
        sql = sql.limit(projection[key])
      }
      if (key === 'skip') {
        sql = sql.skip(projection[key])
      }
      if (key === 'sort') {
        Object.keys(projection.sort).forEach(sortKey => {
          sql = sql.orderBy(sortKey, projection.sort?.[sortKey] === 1 ? 'asc' : 'desc')
        })
      }
    })

    const result = await sql.get()
    return result?.data
  }

  /**
   * 插入单条数据
   * @param document
   */
  async insertOne(document: Record<string, any>) {
    const res = await this.db.collection(this.dbName).add({
      // data 字段表示需新增的 JSON 数据
      data: document
    })
    return res?._id
  }

  /**
   * 插入多条数据
   * @param documents 插入对象
   */
  async insertMany(documents: Record<string, any>[]) {
    const res = await Promise.all(documents.map(doc => this.db.collection(this.dbName).add({ data: doc })))
    return res
  }

  /**
   * 更新数据
   * @param query
   * @param options
   */
  async update(query: Record<string, any>, options?: Record<string, any>) {
    const formatedQuery = formatDBQuery(this.db, query)

    const res = await this.db
      .collection(this.dbName)
      .where(formatedQuery)
      .update({
        data: formatUpdateOperator(this.db, options as any)
      })

    return res?.stats?.updated ? 1 : 0
  }

  /**
   * 删除多条数据
   * @param filter
   */
  async delete(filter: Record<string, any>) {
    const formatedQuery = formatDBQuery(this.db, filter)

    return await this.db.collection(this.dbName).where(formatedQuery).remove()
  }

  /**
   * 获取条目数
   * @param query
   * @param options
   */
  async count(query: Record<string, any>, options?: Record<string, any>) {
    if (!Object.keys(query).length) {
      return (await this.db.collection(this.dbName).count()).total
    }
    const formatedQuery = formatDBQuery(this.db, query)

    return (await this.db.collection(this.dbName).where(formatedQuery).count()).total
  }

  /**
   * 聚合查询
   * @param query
   * @param options
   */
  async aggregate(aggregateOperation: Record<string, any> | any[]) {
    return await this.db.collection(this.dbName).aggregate(aggregateOperation)
  }
}
